package com.ld.shieldsb.canalclient.handler.impl;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.ld.shieldsb.canalclient.handler.ICanalDataSyncHandler;
import com.ld.shieldsb.canalclient.handler.config.OuterAdapterConfig;
import com.ld.shieldsb.canalclient.model.Dml;
import com.ld.shieldsb.canalclient.recoder.Recorder;
import com.ld.shieldsb.common.core.io.FileUtils;
import com.ld.shieldsb.common.core.model.Result;
import com.ld.shieldsb.common.core.util.ResultUtil;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.core.util.date.DateUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * 文件处理器，每天创建新文件
 * 
 * @ClassName LoggerHandler
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2021年11月13日 下午4:21:18
 *
 */
@Slf4j
public class Data2RollingFileHandler implements ICanalDataSyncHandler {
    public static final String TYPE_NAME = "file";
    private boolean inited = false; // 初始化字段标识
    private String filePath;
    public static final String PROPERTIES_DESP = "file.path：输出文件路径；"; // OuterAdapterConfig中properties 参数说明，必须有
    private String key; // 唯一标识

    @Override
    public void sync(List<Dml> dmls, Recorder recorder) {
        File file = new File(filePath);

        // 文件不是今天的则追加日期
        if (file.exists() && DateUtil.daysBetween(new Date(file.lastModified()), new Date()) > 0) {
            try {
                String fileNampe = FileUtils.getFileNameWithoutExtension(filePath);
                String fileExtension = FileUtils.getFileExtension(filePath);
                if (fileExtension == null) {
                    fileExtension = "";
                }
                String oldFileName = fileNampe + "-" + DateUtil.getDateString(new Date(file.lastModified())) + "." + fileExtension;
                String hisFilePath = oldFileName;
                int i = 0;
                while (FileUtils.exists(hisFilePath)) { // 判断文件名存在与否，存在则加后缀
                    i++;
                    hisFilePath = oldFileName + "(" + i + ")";
                }
                FileUtils.moveFile(filePath, hisFilePath);
            } catch (IOException e) {
                log.error("重命名失败！", e);
            }
        }
        if (!file.getParentFile().exists()) {
            file.mkdirs(); // 父目录不存在则创建
        }
        try {
            List<String> outList = new ArrayList<>();
            outList.add(DateUtil.getNowDateTime() + " 接收到信息条数：" + dmls.size());
            outList.addAll(dmls.stream().map(JSON::toJSONString).collect(Collectors.toList()));
            FileUtils.writeLines(file, StandardCharsets.UTF_8.name(), outList, true);
        } catch (IOException e) {
            log.error("输出到文件出错", e);
        }
    }

    @Override
    public void init(OuterAdapterConfig configuration) {
        key = configuration.getKey();
        if (log.isWarnEnabled()) {
            log.warn("文件处理器[key:{}]初始化", configuration.getKey());
        }
        Map<String, String> properties = configuration.getProperties();
        filePath = properties.get("file.path");
        if (StringUtils.isEmpty(filePath)) {
            log.error("文件路径未设置，不能使用该处理器！");
            return;
        }
        File file = new File(filePath + ".log"); // 加一个log后缀，防止瞎写写到敏感文件里
        if (!file.getParentFile().exists()) {
            file.mkdirs(); // 父目录不存在则创建
        }
        inited = true; // 标记已经初始化
    }

    @Override
    public void destroy() {
        if (log.isTraceEnabled()) {
            log.trace("文件处理器销毁");
        }
    }

    @Override
    public String getType() {
        return TYPE_NAME;
    }

    @Override
    public boolean getInit() {
        return inited;
    }

    @Override
    public Result testConn() {
        return ResultUtil.success("");
    }

    @Override
    public String getKey() {
        return key;
    }

    @Override
    public Result syncSingle(Dml dml, int dataIndex, String targetDb, String targetTable, Recorder recorder) {
        return ResultUtil.error("该处理器无需单条同步");
    }

}
